/**
 * @file main.c
 * @author He Chuanxi
 * @brief I.MX6ULL 开发板裸机实验2 C 语言点灯。使用 C 语言来点亮开发板上的 LED 灯，
 *       学习和掌握如何用 C 语言来完成对 I.MX6ULL 处理的 GPIO 初始化和控制、
 * @version 0.1
 * @date 2023-08-22
 * 
 * @copyright Copyright (c) 2023
 * 
 */
#include "main.h"

/**
 * @brief ：使能 I.MX6ULL 所有外设时钟
 * @param ：无
 * @return：无
 */
void clk_enable(void)
{
    CCM_CCGR0 = 0xFFFFFFFF;
    CCM_CCGR1 = 0xFFFFFFFF;
    CCM_CCGR2 = 0xFFFFFFFF;
    CCM_CCGR3 = 0xFFFFFFFF;
    CCM_CCGR4 = 0xFFFFFFFF;
    CCM_CCGR5 = 0xFFFFFFFF;
    CCM_CCGR6 = 0xFFFFFFFF;
}

/**
 * @brief : 初始化 LED 对应的 GPIO
 * @param ：无
 * @return：无
 */
void led_init(void)
{
    /* 1、初始化 IO 服用，复用为 GPIO1_IO03 */
    SW_MUX_GPIO1_IO03 = 0x5;
    /* 2、配置 GPIO1_IO03 的 IO 属性
     * bit 16:0 HYS关闭
     * bit [15:14]:00 默认下拉
     * bit [13]：0 kepper功能
     * bit [12]: 1 pull/kepper使能
     * bit [11]: 0 关闭开路输出
     * bit [7:6]:10 速度100MHz
     * bit [5:3]:110 R0/6驱动能力
     * bit [0]: 0 低转换率
     */
    SW_PAD_GPIO1_IO03 = 0x10B0;
    /* 3、初始化 GPIO, GPIO1_IO03 设置为输出 */
    GPIO1_GDIR = 0x00000008;
    /* 4、设置 GPIO1_IO03 输出低电平，打开 LED0 */
    GPIO1_DR = 0x0;
} 

/**
 * @brief 打开 LED 灯
 * @param 无
 * @return 无
 */
void led_on(void)
{
    GPIO1_DR &= ~(1<<3); /* 将 GPIO1_DR 的 bit3 清零 */
}

/**
 * @brief 关闭 LED 灯
 * @param 无
 * @return 无
 */
void led_off(void)
{
    GPIO1_DR |= (1<<3); /* 将 GPIO1_DR 的 bit3 置 1 */
}

/**
 * @brief 短时间延时函数
 * 
 * @param n 要延时循环次数（空操作循环次数，模式延时）
 * @return 无
 */
void delay_short(volatile unsigned int n)
{
    while (n--) { }
}

/**
 * @brief 延时函数，在396MHz的主频下，延时时间大约为 1ms
 * 
 * @param n 要延时的 ms 数
 * @return 无
 */
void delay(volatile unsigned int n) 
{
    while (n--) {
        delay_short(0x7ff);
    }
}

/**
 * @brief main 函数
 * @param 无
 * @return 无 
 */
int main(void)
{
    clk_enable();   /* 使能所有时钟 */
    led_init();     /* 初始化 led */

    while (1) {
        led_off();  /* 关闭 led */
        delay(500); /* 延时大约 500ms */
        led_on();   /* 打开 led */
        delay(500); /* 延时大约 500ms */
    }

    return 0;
}
